<template>
    <div id="runonceContainer">
        <el-dialog v-model="showRunOnce" width="40%" @open="open" @closed="close" class="run-once forbid-select"
            :show-close="false" top="15vh" :close-on-click-modal="closeClickModal" ref="runOnceRef">
            <template #header v-if="props.jobName">
                <h3>任务名称：{{ props.jobName }}</h3>
            </template>
            <el-divider content-position="left">执行计划</el-divider>
            <div style="display: flex;justify-content: space-between;width: 99%;">
                <el-radio v-model="runInfo.runType" :value="1">立即执行</el-radio>
                <el-radio v-model="runInfo.runType" :value="2">预约执行</el-radio>
            </div>
            <div ref="dateRef" style="position: relative;padding-top: 8px;">
                <el-date-picker v-model="runInfo.runTime" type="datetime" placeholder="预约执行的计划执行时间"
                    :default-time="defaultTime()" :disabled-date="disabledDate" class="input-auto-resize"
                    :teleported="false" popper-class="poper-class" value-format="YYYY-MM-DD HH:mm:ss"
                    :disabled="runInfo.runType === 1" @visible-change="visibleChange" />
            </div>
            <el-divider content-position="left">执行参数</el-divider>
            <tooltip v-model="paramsStr" placeholder="请输入任务参数" dblcopy showTips border>
                <template #suffix>
                    <el-icon style="cursor: pointer;" @click.stop="showParam = true" @dblclick.stop
                        v-show="propsParams.length">
                        <component :is="getIcon('DArrowRight')" />
                    </el-icon>
                </template>
            </tooltip>
            <el-divider content-position="left">执行机器</el-divider>
            <el-select v-model="runInfo.addressList" class="input-auto-resize" placeholder="不选择则根据任务设置自动获取执行器地址"
                clearable @visible-change="visibleChange" popper-class="normal-poper">
                <el-option v-for="(agent, index) in props.agentList" :label="`${agent.title} - ${agent.address}`"
                    :value="agent.address" :key="index" />
            </el-select>
            <template #footer>
                <el-button @click="closeDialog" :icon="getIcon('close')" circle class="button-auto-resize" />
                <el-button @click="runOnce" type="primary" :icon="getIcon('check')" circle class="button-auto-resize" />
            </template>
        </el-dialog>
        <el-drawer v-model="showParam" direction="rtl" size="50%" :show-close="false" :with-header="false"
            @close="closeParamDrawer" @open="openParamDrawer" class="params-drawer forbid-select"
            :before-close="beforeCloseParamDrawer">
            <div v-for="(item, index) in params" class="param-container" :key="index">
                <div class="param">
                    <div style="display: flex;">
                        <div class="param-value-title">参数名称：</div>
                        <div class="param-value-value">{{ item.name }}</div>
                    </div>
                    <div style="display: flex;">
                        <div class="param-value-title">参数类型：</div>
                        <div class="param-value-value" style="width: 250px">
                            <el-radio-group v-model="item.type" class="ml-4">
                                <el-radio :value="1" size="large">常量</el-radio>
                                <el-radio :value="2" size="large">从SQL中取值</el-radio>
                            </el-radio-group>
                        </div>

                        <transition name="animate__animated " enter-active-class="animate__zoomIn animate__fast"
                            leave-active-class="animate__zoomOut animate__fast">
                            <el-row style="width: calc(100% - 400px);" v-show="item.type === 2">
                                <el-col :span="12" style="padding-right: 10px;">
                                    <el-select v-model="dbType[item.name]" placeholder="请选择数据库"
                                        @clear="clearDb(item.name)" @change="clearDb(item.name)"
                                        class="input-auto-resize" popper-class="normal-poper">
                                        <el-option v-for="dbitem in dbTypes" :key="dbitem" :label="dbitem"
                                            :value="dbitem" />
                                    </el-select>
                                </el-col>
                                <el-col :span="12">
                                    <el-select v-model="item.dbSequence" placeholder="请选择实例" class="input-auto-resize"
                                        popper-class="normal-poper">
                                        <el-option v-for="(nameitem, index) in dbNames[item.name]" :key="index"
                                            :label="nameitem.name" :value="nameitem.sequence">
                                        </el-option>
                                    </el-select>
                                </el-col>
                            </el-row>
                        </transition>
                    </div>
                    <div style="display: flex;">
                        <div class="param-value-title">参数值：</div>
                        <div class="param-value-value">
                            <el-input v-model="item.value" class="params-input" />
                        </div>
                    </div>
                    <div style="display: flex;padding-top: 5px;">
                        <div class="param-value-title">参数描述：</div>
                        <div class="param-value-value">
                            <tooltip v-model="item.desc" class="params-input" border/>
                        </div>
                    </div>
                </div>
            </div>

        </el-drawer>
    </div>
</template>

<script setup>
import { getIcon } from "@/utils/tools"
import { useElMessage, useModalSize, useRequest } from "@usehook"
import ElButton from "@/components/button"

let closeClickModal = $ref(true)
let runOnceRef = $ref(null)
const props = defineProps({
    jobName: {
        type: String,
        default: ""
    },
    jobId: {
        type: Number,
        default: ""
    },
    show: {
        type: Boolean,
        default: false
    },
    params: {
        type: Object,
        default: {}
    },
    dbList: {
        type: Object,
        default: {}
    },
    agentList: {
        type: Array,
        default: []
    }
})
let paramsStr = $ref("")
let params = $ref([])

const dateRef = $ref(null)

let propsParams = $computed(() => {
    return props.params ? Object.keys(props.params).map(item => { return { ...props.params[item] } }).filter(e => { return Object.keys(e).length > 0 }) : []
})
const state = reactive({ showRunOnce: props.show })
const { showRunOnce } = toRefs(state)

let dbTypes = $computed(() => Object.keys(props.dbList))
let dbType = $ref({})
let dbNames = $ref({})

watch(() => params, (newParams) => {
    for (let param of newParams) {
        if (param.dbSequence) {
            dbType[param.name] = chooseDbType(param.dbSequence)
        }
    }
}, { deep: true })


watch(() => dbType, (newDbType) => {
    for (let paramName in newDbType) {
        dbNames[paramName] = props.dbList[newDbType[paramName]]
    }
}, { deep: true })

const clearDb = (param) => {
    for (let p of params) {
        if (p.name === param) {
            p.dbSequence = ""
        }
    }
}

const chooseDbType = (dbSequence) => {
    for (let key in props.dbList) {
        const db = props.dbList[key]
        const sequence = db.map(e => {
            return e.sequence
        })
        if (sequence.includes(dbSequence)) {
            return key
        }
    }
    return ""
}

let showParam = $ref(false)
let runInfo = $ref({
    executorParam: {},
    addressList: "",
    runType: 1,
    runTime: ""
})

const openParamDrawer = () => {
    runOnceRef.dialogContentRef.$el.style.transform = 'translateX(100%)'
    runOnceRef.dialogContentRef.$el.style.opacity = 0
    params = propsParams
    for (let param of propsParams) {
        param.value = runInfo.executorParam[param.name] ? runInfo.executorParam[param.name].value : param.value
    }
}

const closeParamDrawer = () => {
    runOnceRef.dialogContentRef.$el.style.transform = 'translateX(0)';
    runOnceRef.dialogContentRef.$el.style.opacity = 1
    runInfo.executorParam = {}
    paramsStr = ""
    for (let param of params) {
        runInfo.executorParam[param.name] = param
        const v = param.name + ":" + (param.type === 1 ? '"' + (param.value || "") + '"' : param.value) + ', '
        paramsStr += v
    }
    paramsStr = paramsStr.substring(0, paramsStr.length - 2)
}

onMounted(() => {
    paramsStr = ""
    for (let param of propsParams) {
        runInfo.executorParam[param.name] = param
        const v = param.name + ":" + (param.type === 1 ? '"' + (param.value || "") + '"' : param.value) + ', '
        paramsStr += v
    }
    paramsStr = paramsStr.substring(0, paramsStr.length - 2)
})

const beforeCloseParamDrawer = (done) => {
    for (let param of params) {
        if (param.type === 2 && !param.dbSequence) {
            useElMessage.error("变量[ " + param.name + " ]数据库不能为空")
            return false
        }
        if (param.type === 2 && !param.value) {
            useElMessage.error("变量[ " + param.name + " ]表达式不能为空")
            return false
        }
    }
    done()
}

const defaultTime = () => {
    const now = new Date()
    now.setSeconds(0)
    now.setMilliseconds(0)
    now.setMinutes(now.getMinutes() + 1)
    return now
}

const disabledDate = (date) => {
    date.setHours(0, 0, 0, 0)
    date.setDate(date.getDate() + 1)
    const today = new Date()
    today.setHours(0, 0, 0, 0)
    return date.getTime() <= today.getTime()
}

const runOnce = () => {
    const { executorParam, addressList, runType, runTime } = runInfo

    if (runInfo.runType == 2 && !runInfo.runTime) {
        useElMessage.error('预约执行时间不能为空')
        return
    }
    useRequest({
        url: '/jobinfo/trigger', id: props.jobId, executorParam: JSON.stringify(executorParam), addressList, runType, runTime, method: "post"
    }).then((resData) => {
        if (resData && resData.status) {
            closeDialog()
            useElMessage('任务已提交')
        } else {
            if (resData.message) useElMessage.error(resData.message)
        }
    })
}

const open = () => {
    useModalSize()
}

const close = () => {
    useModalSize(false)
}

const emits = defineEmits(["cancel"])

const closeDialog = () => {
    showRunOnce.value = !showRunOnce.value
    runInfo = {}
}

const visibleChange = (visible) => {
    setTimeout(() => {
        closeClickModal = !visible
    }, 100)
}

watch(showRunOnce, newVal => {
    if (!newVal) emits("cancel")
})
</script>

<style lang="scss">
.poper-class {
    inset: calc(var(--font-size)* 2 + 15px) auto auto 0;
    width: 100%;
}

.poper-class .el-picker-panel {
    width: 100%;
}

.poper-class .el-date-picker .el-picker-panel__content {
    width: calc(100% - 30px);
}

.poper-class .el-input {
    font-size: var(--font-size) !important;
    font-weight: var(--font-weight) !important;
    height: calc(var(--font-size) * 2) !important;
}

.poper-class .el-time-panel {
    width: 100%;
}

.poper-class .el-time-panel__btn,
.poper-class .el-picker-panel__link-btn,
.poper-class .el-time-panel .el-time-spinner__item,
.poper-class .el-date-picker__header-label,
.poper-class .el-date-table,
.poper-class .el-year-table .cell,
.poper-class .el-month-table .cell {
    font-size: var(--font-size) !important;
    font-family: var(--font-family);
    font-weight: var(--font-weight) !important;
}

.poper-class .el-date-table td.disabled .el-date-table-cell,
.poper-class .el-year-table td.disabled .cell,
.poper-class .el-month-table td.disabled .cell {
    cursor: default;
}

.run-once {
    transition: opacity .3s ease, transform .2s ease;
    overflow: unset;

    h3 {
        margin: 0;
        padding: 3px;
    }

    .el-dialog__header {
        padding-bottom: 0;
    }

    .el-dialog__body {
        padding: 0 30px;
    }

    .el-dialog__footer {
        padding: 20px 30px 10px 10px;
    }
}

#runonceContainer .param-value-title {
    font-size: 18px;
    height: 40px;
    display: flex;
    align-items: center;
    width: 140px;
    justify-content: flex-end;
}

#runonceContainer .param-value-value {
    height: 40px;
    display: flex;
    align-items: center;
    width: calc(100% - 150px);
    font-size: 18px;
}

#runonceContainer .el-radio__label {
    font-size: 18px !important;
    font-weight: var(--font-weight) !important;
    color: var(--font-color) !important;
}

.params-drawer {
    .el-drawer__body {
        padding: 10px;
    }

    .param-container+.param-container {
        padding-top: 10px;
    }
}

#runonceContainer .param {
    width: 100%;
    background: fixed rgba(255, 255, 255, 0.7);
    border-radius: var(--border-radius);
    padding: 10px 0;
}

#runonceContainer .params-input {
    height: 36px !important;
    width: 100% !important;
    font-weight: var(--font-weight) !important;
    font-size: 18px !important;
}

.el-overlay:has(.params-drawer) {
    background: transparent;
}

.el-overlay-dialog:has(.run-once) {
    overflow: hidden;
}
</style>